﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Reflection;

namespace System.IO
{
	public static class FileSystemInfoExtension
	{
		public static bool TryCreate(this DirectoryInfo directoryInfo)
		{
			try { directoryInfo.Create(); }
			catch { }
			return directoryInfo.Exists;
		}

		public static bool TryCreate(this FileInfo fileInfo)
		{
			try { using (FileStream file = fileInfo.Create()) { file.Close(); } }
			catch { }
			return fileInfo.Exists;
		}

		public static bool TryDelete(this FileSystemInfo fileSystemInfo)
		{
			try { fileSystemInfo.Delete(); }
			catch { }
			return !fileSystemInfo.Exists;
		}

		public static DirectoryInfo Combine(this DirectoryInfo root, DirectoryInfo directoryInfo)
		{
			if (directoryInfo == null)
				throw new ArgumentNullException("directoryInfo");
			DirectoryInfo RetVal;
			FieldInfo fi = typeof(FileSystemInfo).GetField("OriginalPath", BindingFlags.Instance| BindingFlags.NonPublic);
			string originalPath1 = (string)fi.GetValue(root);
			string originalPath2 = (string)fi.GetValue(directoryInfo);
			try { RetVal = new DirectoryInfo(Path.Combine(originalPath1, originalPath2)); }
			catch { RetVal = null; }
			return RetVal;
		}

		public static FileInfo Combine(this DirectoryInfo root, FileInfo fileInfo)
		{
			if (fileInfo == null)
				throw new ArgumentNullException("fileInfo");
			FileInfo RetVal;
			FieldInfo fi = typeof(FileSystemInfo).GetField("OriginalPath", BindingFlags.Instance | BindingFlags.NonPublic);
			string originalPath1 = (string)fi.GetValue(root);
			string originalPath2 = (string)fi.GetValue(fileInfo);
			try { RetVal = new FileInfo(Path.Combine(originalPath1, originalPath2)); }
			catch { RetVal = null; }
			return RetVal;
		}

		public static FileSystemInfo Combine(this DirectoryInfo root, string relativePath)
		{
			if (relativePath.LastIndexOf('.') > relativePath.LastIndexOfAny(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }))
			{
				return root.CombineFile(relativePath);
			}
			else
			{
				return root.CombineDirectory(relativePath);
			}
		}

		public static DirectoryInfo CombineDirectory(this DirectoryInfo root, string relativePath)
		{
			if (relativePath == null)
				throw new ArgumentNullException("relativePath");
			FieldInfo fi = typeof(FileSystemInfo).GetField("OriginalPath", BindingFlags.Instance | BindingFlags.NonPublic);
			string originalPath = (string)fi.GetValue(root);
			DirectoryInfo RetVal;
			try { RetVal = new DirectoryInfo(Path.Combine(originalPath, relativePath)); }
			catch { RetVal = null; }
			return RetVal;
		}

		public static FileInfo CombineFile(this DirectoryInfo root, string relativePath)
		{
			if (relativePath == null)
				throw new ArgumentNullException("relativePath");
			FieldInfo fi = typeof(FileSystemInfo).GetField("OriginalPath", BindingFlags.Instance | BindingFlags.NonPublic);
			string originalPath = (string)fi.GetValue(root);
			FileInfo RetVal;
			try { RetVal = new FileInfo(Path.Combine(originalPath, relativePath)); }
			catch { RetVal = null; }
			return RetVal;
		}
	}
}
